home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / a_utils / perl / msds-prl / prl386ld.zoo / popen.c < prev    next >
C/C++ Source or Header  |  1992-07-02  |  4KB  |  189 lines

  1. /* $RCSfile: popen.c,v $$Revision: 4.0.1.1 $$Date: 91/06/07 11:22:52 $
  2.  *
  3.  *    (C) Copyright 1988, 1990 Diomidis Spinellis.
  4.  *
  5.  *    You may distribute under the terms of either the GNU General Public
  6.  *    License or the Artistic License, as specified in the README file.
  7.  *
  8.  * $Log:    popen.c,v $
  9.  * Revision 4.0.1.1  91/06/07  11:22:52  lwall
  10.  * patch4: new copyright notice
  11.  * 
  12.  * Revision 4.0  91/03/20  01:34:50  lwall
  13.  * 4.0 baseline.
  14.  * 
  15.  * Revision 3.0.1.2  90/08/09  04:04:42  lwall
  16.  * patch19: various MSDOS and OS/2 patches folded in
  17.  * 
  18.  * Revision 3.0.1.1  90/03/27  16:11:57  lwall
  19.  * patch16: MSDOS support
  20.  * 
  21.  * Revision 1.1  90/03/18  20:32:20  dds
  22.  * Initial revision
  23.  *
  24.  */
  25.  
  26. /*
  27.  * Popen and pclose for MS-DOS
  28.  */
  29.  
  30. #include <stdlib.h>
  31. #include <stdio.h>
  32. #ifndef DJGPP
  33. #include <process.h>    /* doesn't exist in DJGPP */
  34. #endif /* !DJGPP */
  35.  
  36. /*
  37.  * Possible actions on an popened file
  38.  */
  39. enum action {
  40.     delete,             /* Used for "r". Delete the tmp file */
  41.     execute                /* Used for "w". Execute the command. */
  42. };
  43.  
  44. /*
  45.  * Linked list of things to do at the end of the program execution.
  46.  */
  47. static struct todo {
  48.     FILE *f;            /* File we are working on (to fclose) */
  49.     const char *name;        /* Name of the file (to unlink) */
  50.     const char *command;        /* Command to execute */
  51.     enum action what;        /* What to do (execute or delete) */
  52.     struct todo *next;        /* Next structure */
  53. } *todolist;
  54.  
  55.  
  56. /* Clean up function */
  57. static int close_pipes(void);
  58.  
  59. /*
  60.  * Add a file f running the command command on file name to the list
  61.  * of actions to be done at the end.  The action is specified in what.
  62.  * Return -1 on failure, 0 if ok.
  63.  */
  64. static int
  65. add(FILE *f, const char *command, const char *name, enum action what)
  66. {
  67.     struct todo    *p;
  68.  
  69.     if ((p = (struct todo *) malloc(sizeof(struct todo))) == NULL)
  70.         return -1;
  71.     p->f = f;
  72.     p->command = command;
  73.     p->name = name;
  74.     p->what = what;
  75.     p->next = todolist;
  76.     todolist = p;
  77.     return 0;
  78. }
  79.  
  80. FILE *
  81. mypopen(const char *command, const char *t)
  82. {
  83.     char buff[256];
  84.     char *name;
  85.     FILE *f;
  86.     static init = 0;
  87.  
  88.     if (!init)
  89. #ifndef DJGPP
  90.         if (onexit(close_pipes) == NULL)
  91.             return NULL;
  92.         else
  93. #endif /* !DJGPP */
  94.             init++;
  95.  
  96.     if ((name = tempnam((char*)NULL, "pp")) == NULL)
  97.         return NULL;
  98.  
  99.     switch (*t) {
  100.     case 'r':
  101.         sprintf(buff, "%s >%s", command, name);
  102.         if (system(buff) || (f = fopen(name, "r")) == NULL) {
  103.             free(name);
  104.             return NULL;
  105.         }
  106.         if (add(f, command, name, delete)) {
  107.             (void)fclose(f);
  108.             (void)unlink(name);
  109.             free(name);
  110.             return NULL;
  111.         }
  112.         return f;
  113.     case 'w':
  114.         if ((f = fopen(name, "w")) == NULL) {
  115.             free(name);
  116.             return NULL;
  117.         }
  118.         if (add(f, command, name, execute)) {
  119.             (void)fclose(f);
  120.             (void)unlink(name);
  121.             free(name);
  122.             return NULL;
  123.         }
  124.         return f;
  125.     default:
  126.         free(name);
  127.         return NULL;
  128.     }
  129. }
  130.  
  131. int
  132. mypclose(FILE *f)
  133. {
  134.     struct todo *p, **prev;
  135.     char buff[256];
  136.     const char *name;
  137.     int status;
  138.  
  139.     for (p = todolist, prev = &todolist; p; prev = &(p->next), p = p->next)
  140.         if (p->f == f) {
  141.             *prev = p->next;
  142.             name = p->name;
  143.             switch (p->what) {
  144.             case delete:
  145.                 free(p);
  146.                 if (fclose(f) == EOF) {
  147.                     (void)unlink(name);
  148.                     status = EOF;
  149.                 } else if (unlink(name) < 0)
  150.                     status = EOF;
  151.                 else
  152.                     status = 0;
  153.                 free((void*)name);
  154.                 return status;
  155.             case execute:
  156.                 (void)sprintf(buff, "%s <%s", p->command, p->name);
  157.                 free(p);
  158.                 if (fclose(f) == EOF) {
  159.                     (void)unlink(name);
  160.                     status = EOF;
  161.                 } else if (system(buff)) {
  162.                     (void)unlink(name);
  163.                     status = EOF;
  164.                 } else if (unlink(name) < 0)
  165.                     status = EOF;
  166.                 else
  167.                     status = 0;
  168.                 free((void*)name);
  169.                 return status;
  170.             default:
  171.                 return EOF;
  172.             }
  173.         }
  174.     return EOF;
  175. }
  176.  
  177. /*
  178.  * Clean up at the end.  Called by the onexit handler.
  179.  */
  180. static int
  181. close_pipes(void)
  182. {
  183.     struct todo    *p;
  184.  
  185.     for (p = todolist; p; p = p->next)
  186.         (void)mypclose(p->f);
  187.     return 0;
  188. }
  189.